Skip to content

https://mobileaws.atlassian.net/browse/CLOUD-2712#6

Open
dlopezallcode wants to merge 1 commit intomainfrom
CLOUD-2712
Open

https://mobileaws.atlassian.net/browse/CLOUD-2712#6
dlopezallcode wants to merge 1 commit intomainfrom
CLOUD-2712

Conversation

@dlopezallcode
Copy link
Copy Markdown

Overview

The .NET SDK has been brought to complete parity with the reference Java SDK. Contact Service was added, MD5 caching in MMS with automatic image deduplication, and support for FilesBaseUrl with test/prod switching. The SDK compiles without errors or warnings.


Implemented Changes

1. FilesBaseUrl in config and client (src/CCAI.NET/CCAIClient.cs)

Before: no FilesBaseUrl configuration; GetSignedUploadUrlAsync used hardcoded production URL.

After, in CCAIConfig:

public string FilesBaseUrl { get; init; } = Environment.GetEnvironmentVariable("CCAI_FILES_BASE_URL")
    ?? "https://files.cloudcontactai.com";

public string GetFilesBaseUrl()
{
    return UseTestEnvironment
        ? Environment.GetEnvironmentVariable("CCAI_TEST_FILES_BASE_URL") ?? "https://files-test-cloudcontactai.allcode.com"
        : FilesBaseUrl;
}

In CCAIClient:

  • Public getter GetFilesBaseUrl() that delegates to _config.GetFilesBaseUrl()

2. New service: Contact (src/CCAI.NET/Contact/)

Files created:

  • Contact/ContactService.cs — service logic
  • Contact/SetDoNotTextRequest.cs — request model
  • Contact/ContactResponse.cs — response model

Methods:

// Async
Task<ContactResponse> SetDoNotTextAsync(bool doNotText, string? contactId = null, string? phone = null, CancellationToken cancellationToken = default)

// Sync wrapper
ContactResponse SetDoNotText(bool doNotText, string? contactId = null, string? phone = null)

Endpoint: PUT /account/do-not-text

Payload: { clientId, doNotText, contactId?, phone? }clientId automatically injected from client.

Registered in CCAIClient as:

public ContactService Contact { get; }
// ...
Contact = new ContactService(this);

3. MD5 Cache in MMS (src/CCAI.NET/SMS/MMSService.cs)

Before: SendWithImageAsync() always uploaded the image using Path.GetFileName() as filename, without checking for duplicates.

After: complete flow with MD5 hash deduplication.

New private/public methods:

// Private — computes MD5 of file
private static string ComputeMD5(string filePath)

// Public — checks if file already exists in S3
Task<StoredUrlResponse> CheckFileUploadedAsync(string fileKey, CancellationToken cancellationToken = default)
StoredUrlResponse CheckFileUploaded(string fileKey)  // sync wrapper

SendWithImageAsync() rewritten:

  1. Computes MD5 of file → constructs {clientId}/campaign/{md5}.{ext} as fileKey
  2. Calls CheckFileUploadedAsync(fileKey) — if storedUrl is not empty, skips upload
  3. If doesn't exist: gets signed URL → uploads → sends
  4. Sends MMS with calculated fileKey

Bonus fix: GetSignedUploadUrlAsync() now uses _client.GetFilesBaseUrl() instead of hardcoded URL "https://files.cloudcontactai.com/upload/url".

New model: src/CCAI.NET/SMS/StoredUrlResponse.cs

public class StoredUrlResponse
{
    [JsonPropertyName("storedUrl")]
    public string StoredUrl { get; set; } = string.Empty;
}

@dlopezallcode dlopezallcode marked this pull request as ready for review April 16, 2026 19:09
Comment thread src/CCAI.NET/SMS/MMSService.cs
Comment thread src/CCAI.NET/SMS/MMSService.cs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants